package com.bitcoin.scheduler.websocket.client;

import okhttp3.OkHttpClient;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Converter;
import retrofit2.Response;
import retrofit2.converter.jackson.JacksonConverterFactory;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

public class ApiServiceGenerator {
    private static final OkHttpClient sharedClient = new OkHttpClient.Builder()
        .pingInterval(20, TimeUnit.SECONDS)
        .proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 1080)))
        .build();

    private static final Converter.Factory converterFactory = JacksonConverterFactory.create();

    @SuppressWarnings("unchecked")
    private static final Converter<ResponseBody, ApiError> errorBodyConverter =
        (Converter<ResponseBody, ApiError>) converterFactory.responseBodyConverter(
            ApiError.class, new Annotation[0], null);

    /**
     * Execute a REST call and block until the response is received.
     */
    public static <T> T executeSync(Call<T> call) {
        try {
            Response<T> response = call.execute();
            if (response.isSuccessful()) {
                return response.body();
            }
            else {
                ApiError apiError = getApiError(response);
                throw new ApiException(apiError);
            }
        } catch (IOException e) {
            throw new ApiException(e);
        }
    }

    /**
     * Extracts and converts the response error body into an object.
     */
    public static ApiError getApiError(Response<?> response) throws IOException, ApiException {
        return Objects.requireNonNull(errorBodyConverter).convert(Objects.requireNonNull(response.errorBody()));
    }

    /**
     * Returns the shared OkHttpClient instance.
     */
    public static OkHttpClient getSharedClient() {
        return sharedClient;
    }
}
